﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GGEditor.API;
using GGEditor.Core.UI;
using WeifenLuo.WinFormsUI.Docking;

namespace GGEditor.Windows
{
	class DockingWindowManager : IWindowManager
	{
		private readonly DockPanel dockPanel;
		private readonly IList<IWindow> windows = new List<IWindow>();

		public DockingWindowManager(DockPanel dockPanel)
		{
			this.dockPanel = dockPanel;
			dockPanel.ActiveDocumentChanged += OnActiveDocumentChanged;
		}

		void OnActiveDocumentChanged(object sender, EventArgs e)
		{
			WindowActivated(this, ActiveWindow);
		}

		IWindow ActiveWindow
		{
			get
			{
				return dockPanel.ActiveContent as IWindow;
			}
		}

		#region Implementation of IWindowManager

		public IEnumerable<IWindow> Windows
		{
			get { return windows; }
		}

		public IEnumerable<IWindow> DocumentWindows
		{
			get
			{
				foreach (IWindow window in Windows)
				{
					if (window.IsDocument)
						yield return window;
				}
			}
		}

		public IEnumerable<IWindow> PadWindows
		{
			get
			{
				foreach (IWindow window in Windows)
				{
					if (!window.IsDocument)
						yield return window;
				}
			}
		}

		#endregion

		public IWindow CreateWindow(WindowParameters wp)
		{
			Window window = new Window(dockPanel, wp);

			windows.Add(window);
			return window;
		}

		public void DestroyWindow(IWindow window)
		{
			if (!windows.Remove(window))
				throw new InvalidOperationException();
			window.Close();
		}

		public event WindowEventHandler WindowCreated = delegate { };

		public event WindowEventHandler WindowDestroyed = delegate { };

		public event WindowEventHandler WindowActivated = delegate { };

		class Window : DockContent, IWindow
		{
			#region Implementation of IWindow

			private Control content;
			private readonly DockPanel dockPanel;

			public Window(DockPanel dockPanel, WindowParameters wp)
			{
				this.dockPanel = dockPanel;
				Text = wp.Text;
				Content = wp.Content;
				Visible = wp.Visible;
				IsDocument = wp.IsDocument;
				DockAreas = wp.IsDocument
					? DockAreas.Document | DockAreas.Float
					: DockAreas.Document | DockAreas.Float
					| DockAreas.DockTop | DockAreas.DockLeft
					| DockAreas.DockBottom | DockAreas.DockRight;
				if (!wp.IsDocument)
					switch (wp.Dock)
					{
						case WindowParameters.DockState.Top:
							DockState = DockState.DockTop;
							break;
						case WindowParameters.DockState.Left:
							DockState = DockState.DockLeft;
							break;
						case WindowParameters.DockState.Bottom:
							DockState = DockState.DockBottom;
							break;
						case WindowParameters.DockState.Right:
							DockState = DockState.DockRight;
							break;
						default:
							throw new ArgumentOutOfRangeException();
					}
			}

			public Control Content
			{
				get { return content; }
				set
				{
					SuspendLayout();

					if (content != null)
					{
						Controls.Remove(content);
					}

					content = value;

					if (content != null)
					{
						content.Dock = DockStyle.Fill;
						Controls.Add(content);
					}

					ResumeLayout(true);
				}
			}

			public new bool Visible
			{
				get
				{
					return base.Visible;
				}
				set
				{
					if (value)
						Show(dockPanel);
					else
						base.Visible = false;
				}
			}

			public bool IsDocument { get; private set; }

			#endregion
		}
	}
}
